package edu.rit.varapp.datalayer;

import edu.rit.varapp.db.DatabaseConnection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;

/**
 * ModuleOps provides methods to perform various functions on the database in relation to Module objects.
 */
public class ModuleOps {

    private DatabaseConnection conn;

    public ModuleOps( DatabaseConnection conn ) {
        this.conn = conn;
    }

    /**
     * Inserts a new module in the database.
     * @param module The module information that we want to insert.
     * @return True if information has been successfully written, false otherwise.
     * @throws SQLException
     */
    public boolean insertModule( Module module ) throws SQLException {
        String sql = "INSERT INTO modules (" + Module.columnsToSQL() + ") VALUES (" + module.valuesToSQL() + ")";
        int val = conn.executeUpdateQuery( sql );
        if( val > 0 ) {
            return true;
        }
        return false;
    }

    /**
     * Deletes a module from the database.
     * @param module The module to delete.
     * @return True if the information has been successfully deleted, false otherwise.
     * @throws SQLException
     */
    public boolean deleteModule( Module module ) throws SQLException {
        String sql = "DELETE FROM modules WHERE SerialNumber = " + module.getSerialNumber();
        int val = conn.executeUpdateQuery( sql );
        if( val > 0 ) {
            return true;
        }
        return false;
    }

    /**
     * Updates a module with the given information. This is done by deleting the existing module, and inserting
     * a "new" module.
     * @param module The existing module to update.
     * @return True if the module has been updated correctly, false otherwise.
     * @throws SQLException
     */
    public boolean updateModule( Module module ) throws SQLException {
        if( deleteModule( module ) ) {
            if( insertModule( module ) ) {
                return true;
            }
        }
        return false;
    }

    /**
     * Retrieves all existing modules for a certain customer.
     * @param customer The customer we want to retrieve modules for.
     * @return The collection of current modules for the customer.
     * @throws SQLException
     */
    public ArrayList<Module> retrieveModules( Customer customer ) throws SQLException {
        ArrayList<Module> ret = new ArrayList<Module>();
        String sql = "SELECT " + Module.columnsToSQL() + " FROM modules JOIN customer USING (EntityId)"
                     + " WHERE EntityId = " + customer.getEntityId();
        ResultSet rs = conn.executeQuery( sql );
        ArrayList<ArrayList<String>> data = conn.getData( rs, false );

        for( ArrayList<String> row : data ) {
            try {
                ret.add( buildModule( row ) );
            } catch( ParseException pe ) {
                //TODO: not sure what to do here... this would be a major problem
                System.err.println( "Big problem parsing a date object: " + pe.getMessage() );
                pe.printStackTrace();
            }
        }
        return ret;
    }

    /**
     * Builds a Module object from a row of data.
     * @throws ParseException Will be thrown if the data for any Date objects are invalid.
     */
    private Module buildModule( ArrayList<String> data ) throws ParseException {
        return new Module( Integer.parseInt( data.get( 0 ) ),
                           Integer.parseInt( data.get( 1 ) ),
                           data.get( 2 ),
                           data.get( 3 ),
                           DateFormat.getDateInstance().parse( data.get( 4 ) ),
                           Integer.parseInt( data.get( 5 ) ),
                           Integer.parseInt( data.get( 6 ) ),
                           Integer.parseInt( data.get( 7 ) ),
                           Integer.parseInt( data.get( 8 ) ),
                           Integer.parseInt( data.get( 9 ) ),
                           Integer.parseInt( data.get( 10 ) ),
                           Integer.parseInt( data.get( 11 ) ),
                           Boolean.parseBoolean( data.get( 12 ) ),
                           Boolean.parseBoolean( data.get( 13 ) ),
                           Boolean.parseBoolean( data.get( 14 ) ),
                           data.get( 15 ),
                           data.get( 16 ),
                           DateFormat.getDateInstance().parse( data.get( 17 ) ) );
    }
}
